class Animal:

    def __init__(self) -> None:
        self.__name = "animal"
        self.age = 12

    def eat(self):
        print("吃")

    def run(self):
        print("Animal 跑")

    def __test(self):
        print("animal test")

    # 可以定义一个公有方法供外界访问自己的私有方法/属性
    def test(self):
        print(self.__name)
        self.__test()


class Pet:
    def say(self):
        print("pet say")

    def run(self):
        print("Pet 跑")


# Dog继承Animal
# Animal是Dog的基类，Dog是从Animal类派生的派生类
# 子类中无法访问父类的私有属性/方法
# 可以多重继承(避免多个父类有相同的属性/方法)
class Dog(Animal, Pet):
    def bark(self):
        print("汪汪叫")

    # 方法重写
    def run(self):
        # 调用父类方法，super是一个特殊类，super()对象就是super创建的
        super().run()
        print("疯狂的跑")

    def eat(self):
        # 在python2.0前调用父类方法,不建议使用
        Animal.eat(self)
        print("狗疯狂吃")

    def dog_test(self):
        # 访问父类的私有属性/方法，间接通过父类的公有方法
        self.test()


dog = Dog()
dog.bark()
dog.eat()
dog.test()
dog.say()
dog.run()

# 如果多个父类有相同方法，按照MRO返回的顺序从左往右查找
# MRO：方法搜索顺序，类的内置属性__mro__
# (<class '__main__.Dog'>, <class '__main__.Animal'>, <class '__main__.Pet'>, <class 'object'>)
print(Dog.__mro__)


# 新式类(以object为基类的类)、旧式类(不以object为基类的类)
# object中定义很多属性/方法，python3.x默认继承object，而2.x必须指定继承object
# 为了兼容2.0定义的类最好显示继承object类

# 多态
class Letter(object):
    def say(self):
        print("字母say")


class A(Letter):
    def say(self):
        print("A say")


class B(Letter):
    def say(self):
        print("B say")


class Stu(object):

    def study(self, letter):
        letter.say()


s = Stu()
s.study(A())
s.study(B())
